home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-03
/
dosbas.zip
/
FILES.ASM
< prev
next >
Wrap
Assembly Source File
|
1990-12-19
|
24KB
|
664 lines
;«RM82»«TS8,16,24,32,40,48»
;updated 11/21/90
;============================================================================
; Copyright (C) Copr. 1990 by Sidney J. Kelly
; All Rights Reserved.
; Sidney J. Kelly
; 150 Woodhaven Drive
; Pittsburgh, PA 15228
; home phone 412-561-0950 (7pm to 9:30pm EST)
;============================================================================
DOSSEG
.MODEL MEDIUM
Public GETDRIVE, GETSUB, DRVSPACE, SETDRIVE, SUBEXIST, FLOPPYREADY, FLOPPYDRIVES, HARDRIVES, GETCURRENTNAME, TRUENAME, GETFULLPATH
.CODE
; Please do not remove
Copyright DB 13,10,'Copyright Copr. (C) 1990 Sidney J. Kelly',13,10
Copyright1 DB 'All Rights Reserved',13,10,26
;============================================================================
; DECLARE SUB GETDRIVE(DRIVE$)
; CALL GETDRIVE(DRIVE$)
; Returns current drive name
; If LEN(DRIVE$)=0 then nothing happens
;
; Assumes that DRIVE$ is a near string, not TYPEd or part of a far string
; array. In other words, assumes DRIVE$ is in DGROUP
;============================================================================
EVEN
GETDRIVE PROC FAR
Push BP
Mov BP,SP ;save base frame
Mov BX,[BP+6]
Mov CX,[BX]
Jcxz Error1 ;test LEN(Drive$) if 0 exit
Mov AH,19h
Int 21h
Add AL,'A' ;Add A to value
Xor AH,AH ;clear AH to 0
Mov BX,[BP+6] ;get address of string descripter
Mov BX,[BX+2] ;get actual string address
Mov [BX],AL ;store AL in Drive$
Error1:
Pop BP
Ret 2 ; one parameter passed
; so remove it
GETDRIVE ENDP
;============================================================================
; DECLARE SUB GETSUB (PATH AS STRING * 64, PATHLEN%)
; Returns current subdirectory path, without Drive:\, (i.e. no "A:\")
; if LEN(Path$) not = to 64 then returns a pathlen% of -1
;
; PATH$ can not be a TYPEd string or a variable in a string array
; because there is a chance that string will be outside DGROUP.
; This routine assumes that Path$ is a near string.
;============================================================================
EVEN
GETSUB PROC FAR
Push BP ;set up base pointer
Mov BP,SP ;allow us to address the stack
Push SI ;save index registers
Push DI ; ditto
Mov AX,SS
Mov ES,AX ;set ES = to DGROUP for scasb
assume ES:@data
Mov BX,[BP+8] ;get address of Path$
Mov AX,ES:[BX]
Cmp AX,64 ;if LEN(PATH$) <> 64
JNE Error ;then Error
Mov SI,ES:[BX+2] ;it has to be 64 so Pathlen% value is
Mov DI,SI ;calculated correctly below
Xor DL,DL ;select default drive
Mov AH,47h ;get current directory
Int 21h
JC Error ;if carry set, directory invalid
Mov CX,64 ;determine length of Path$
Xor AL,AL ;clear AL, the value to search
;for ending null
Cld ;clear direction flag
Repnz Scasb ;scan until reach end of Path$
Mov AX,63 ;determine length of Path$
Sub AX,CX
Jmp Short finis
Error:
Mov AX,-1 ;return Pathlen% = -1 if error
finis:
Mov BX,[BP+6]
Mov ES:[BX],AX
Pop DI ;restore registers used
Pop SI
Pop BP
Ret 4
GETSUB ENDP
;============================================================================
; DECLARE SUB DRVSPACE (DRIVE$,SPACE&)
; checks if DRIVE$ <"A" or >"z", or if >"Z" & less <"a"
; Drive of "@" gives the current drive
; Invalid DRIVE$ gives a free space of 0
; Note: DOS does not correctly adjust this if use JOIN or SUBST and
; try to determine the size of a non-default drive.
;============================================================================
EVEN
DRVSPACE PROC FAR
Push BP
Mov BP,SP
Mov BX,[BP+8] ;get drive letter from first parameter
Mov CX,[BX]
Jcxz Error_Set ;DRIVE$ is a null string so exit
Mov BX,[BX+2] ;get string address
Mov DL,[BX] ;store string in DL
Xor DH,DH
Cmp DL,'@' ;check if less than "@"
JB Error_Set
Cmp DL,'z' ;check if > "z"
JA Error_Set
Cmp DL,'@' ;select current if "@"
JNE Spec_drive ;check if want current drive
Mov AH,36h
Xor DX,DX ;0 is current drive number
Int 21h ;read current drive free space
Cmp AX,0ffffh ;did an error occur?
JE Error_Set ;routine returned invalid drive
Jmp Short Quit ;valid drive
Spec_drive:
And DL,1fh ;allow A to Z or a to z
Dec DL
Cmp DX,19h ;final range check if > "Z" and < "a"
JA Error_Set ;greater than "Z" so quit
Inc DL
Mov AH,36h
Int 21h
Cmp AX,0ffffh ;did an error occur?
JE Error_Set
Quit: ;store free SPACE& in DX:AX pair
Mul CX ;multiply sectors/cluster * bytes per sector
Mul BX ;multiply product by no. free clusters
Jmp Short Finis1 ;the order of math is important
Error_Set:
Xor AX,AX ;returns a free SPACE& of 0
Mov DX,AX ;saves a clock on 8086 chips
Finis1:
Mov BX,[BP+6] ;Stores the SPACE& in 2d parameter
Mov [BX],AX ;store lowbyte from AX
Mov [BX+2],DX ;store hibyte from DX
Pop BP
Ret 4
DRVSPACE ENDP
;============================================================================
; DECLARE SUB SETDRIVE (DRIVE$,ErrCode%)
; no change occurs if DRIVE$ <"A" or >"z", or if >"Z" & less <"a"
; Returns ErrCode% = 0 (False) if no errors
; = -1 (True) if errors
; error checking includes range check and real test if a change occured
;============================================================================
EVEN
SETDRIVE PROC FAR
Push BP
Mov BP,SP ;set base frame pointer
Mov AH,19h ;get default drive
Int 21h
Xor CH,CH
Mov CL,AL ;store in CL
Mov BX,[BP+8] ;get drive letter from first parameter
Mov BX,[BX+2] ;get string address
Mov DL,[BX] ;store string in DL
Xor DH,DH
Cmp DL,'A' ;check if less than "A"
JB Error_Set1
Cmp DL,'z' ;check if > "z"
JA Error_Set1
And DL,1fh ;allow A to Z or a to z
Dec DL ;subtract one to make DX zero based drive number
Cmp DL,19h ;final range check if > "Z" and < "a"
JA Error_Set1 ;greater than "Z" so quit
Cmp CL,DL
je Quiter ;current equal's new drive so don't bother
Mov AH,0Eh ;change drive
Int 21h
Mov AX,1900h ;get current directory again to
;see if change worked
Int 21h
Cmp AL,DL ;DL holds user selected drive
JNE Error_Set1 ;unable to make a change so set error
Quiter:
Xor AX,AX ;clears ERRORCODE% to 0
Jmp Short Finis2
Error_Set1:
Mov AX,-1 ;Sets ERRORCODE% to -1 if error occured
Finis2:
Mov BX,[BP+6] ;Stores the ERRORCODE% in 2d parameter
Mov [BX],AX
Pop BP
Ret 4
SETDRIVE ENDP
;============================================================================
; DECLARE SUB SUBEXIST (PATH$+CHR$(0),ErrCode%)
; Returns ErrCode% = 0 (False) if no errors,
; = -1 (True) if errors
; If a drive change is required, subdirectory on other drive will be made
; the "current" subdirectory on that other drive.
;
; PATH$ cannot be a TYPEd string or a variable in a string array
; because there is a chance that string will be outside DGROUP. String
; cocentenation is used to make sure it is in DGROUP.
;============================================================================
EVEN
StoragePath db 0,':\', 64 dup (0) ;temporarily store information.
;By storing DATA in code seg,
;this routine cannot be used
;under OS/2. We do it
;to save space in DGROUP
EVEN
SUBEXIST PROC FAR
Push BP
Mov BP,SP
Push DS
Push SI
Push DI
Mov AH,19h ;get original drive
Int 21h
Mov StoragePath,AL ;store drive number for later use
Push DS ;save DS
Mov AX,CS ;faster than PUSH CS, POP DS on 8088
Mov DS,AX ;set DS == CS
Mov AH,47h ;get original subdirectory
Xor DL,DL ;of current drive
ASSUME DS:@code ;tell DOS of change
Mov SI, offset StoragePath+3 ;give original path
Mov DI, SI
Int 21h
Pop DS
ASSUME DS:@data
Mov BX,[BP+8] ;get Path$
Mov DI,[BX+2] ;store address of Path$ in DI
Mov CX,[BX] ;get length of string in CX
Jcxz String_Too_Short;if Path$ too short, bail out
Cmp CX,03 ;check string size
JB Short_Path ;if LEN(Path$) < 3,
;don't check for drive
Cmp byte PTR [DI+1],':' ;check for colon
JNE Short_Path ;skip drive check if no colon
Mov DL,[DI] ;drive letter to DL
And DX,001fh ;capitalize letter
Dec DX ;reduce by zero, for zero bias
Mov AH,0Eh ;select drive
Int 21h
Inc DI ;move pointer past DRIVE
Inc DI ;move pointer past colon
Short_Path:
Mov DX,DI ;move pointer to DX
Mov AH,3Bh ;change to new "current" directory
Mov SI,-1 ;assume error
Int 21h
JC SubEx_Err ;error if carry set
Xor SI,SI ;no error so return 0
SubEx_Err:
Mov BX,[BP+6]
Mov [BX],SI ;store result from SI in ErrCode%
Mov DL, StoragePath ;using original default drive
Mov AH,0Eh ;select original drive
Int 21h
Add DL,65 ;convert drive letter to ASCII character
Mov StoragePath,DL ;give us original drive letter
Mov AX,CS ;set DS == CS
Mov DS,AX
Mov AH,3Bh ;change back to original subdirectory
ASSUME DS:@code, ES:NOTHING
Mov DX, offset StoragePath
Int 21h
SubEx_Finis:
Pop DI ; restore saved registers
Pop SI
Pop DS
ASSUME DS:@data
Pop BP
Ret 4 ; remove 2 * 2 parameters
String_Too_Short:
Mov SI,-1 ;Path$ a "" string, why bother
Mov BX,[BP+6] ;report ErrCode of TRUE
Mov [BX],SI ;store result from SI in ErrCode%
Jmp Short SubEx_Finis
SUBEXIST ENDP
;============================================================================
; DECLARE SUB FLOPPYREADY (DRIVE$, ErrCode%)
; Tests if floppy drive is ready, on a one floppy system
; treats drive B: as equivalent to drive A:
; ErrCode
; 128 = Time Out Error
; 80 = Track error
; -1 = Drive$ is not valid
; 0 = All a.o.k.
; Note : A critical error routine is not necessary for this routine to work
;============================================================================
EVEN
FLOPPYREADY PROC FAR
Push BP
Mov BP,SP
Push SI
call _Floppy ;get actual # of floppies in AX
Mov SI,0003 ;assume 3 drives
Mov BX,[BP+8]
Mov CX,[BX] ;test LEN(DRIVE$)
Jcxz ErrorFound ;if zero, then quit
Mov BX,[BX+2] ; get actual string
Mov DL,[BX] ;store in DL
And DL,1Fh ;capitalize it
Cmp DL,2
JNE @f ;Check if want drive B: on
Cmp AL,1 ;a one floppy system
JNE @f
Dec DL ;make call for B:, mimic A:
@@:
Cmp DL,AL ;if greater than allowed floppy #
JA ErrorFound
Dec DL ;zero bias
Redo:
Mov AX,401h
Mov CX,1
Xor DH,DH ;verify 1 sector of disk
Int 13h
Or AH,AH ;check for errors
Mov AX,0000 ;can't use XOR because
;wd change flags
JZ NormalExit ;found none so exit
Dec SI ;decriment no. of drives
JZ @f ;jump if no more drives
Xor AH,AH ;reset drive if error
Int 13h ;try again
Jmp Short Redo
@@:
Mov AX,0100h ;read reset status
Int 13h
Xchg AH,AL ;put return value in AL
Xor AH,AH ;clear AH
NormalExit:
Mov BX,[BP+6]
Mov [BX],AX ;store in ErrCode
Pop SI ;restore saved registers
Pop BP
Ret 4 ;remove 2 * 2 parameters
ErrorFound:
Mov AX,-1 ;return -1 for error
Jmp NormalExit
FLOPPYREADY ENDP
;---------------------------------------------------------------------
; DECLARE SUB FLOPPYDRIVES(NoDrives%)
; Returns number of physical floppy drives in system
;---------------------------------------------------------------------
EVEN
FLOPPYDRIVES PROC FAR
Push BP
Mov BP,SP
Call _Floppy
Mov BX,[BP+6]
Mov [BX],AX ;store AX in value
Pop BP
Ret 2
FLOPPYDRIVES ENDP
EVEN
_Floppy Proc Near
Int 11h
Shr AX,1 ;test if have any floppies
JB @f ;jump if carry flag set
Xor AX,AX ;else clear AX
Jmp Short Fins1 ;quit
@@:
And AX,60h ;mask off floppy bits
Mov CL,05 ;count the number of floppies
Shr AX,CL
Inc AX ;increment the final count
Fins1:
Ret
_Floppy ENDP
;---------------------------------------------------------------------
; DECLARE SUB HARDDRIVES(NoDrives%)
; Returns number of physical hard disks in system
;---------------------------------------------------------------------
EVEN
HARDRIVES PROC FAR
Push BP
Mov BP,SP
Xor AX,AX
Mov ES,AX
Mov BX,ES:[0475h] ; get info from 0040:0075h
Mov AX,BX
And AX,3 ; keep within range 0-4
Mov BX,[BP+6]
Mov [BX],AX ; store AX in value
Pop BP
Ret 2
HARDRIVES ENDP
;=========================================================================
; DECLARE SUB GETCURRENTNAME (FName as STRING * 64, FileLength%)
; Returns current filename for dos version 3.xx and above
; if LEN(FName$) <> 64 then returns a FileLength% of -1
;
; FName$ can not be a TYPEd string or a variable in a string array
; because there is a chance that string will be outside DGROUP.
; This routine assumes that FName$ is a near string.
; Function returns an error if DOS version < 3.xx since function is not
; supported for that version.
;=========================================================================
EVEN
Env_Seg dw 0
Env_Len dw 0
EVEN
GETCURRENTNAME PROC FAR
Push BP ; set up base pointer
Mov BP,SP ; allow us to address the stack
Push SI ; save index registers
Push DI ; ditto
Push DS ; save segment registers
Mov AH,30h ; check if DOS version > 2.xx
Int 21h
Cmp AL,3
JB Error12 ; error if less than 3.00
Cld ; clear direction flag
Mov AH,62h ; get PSP address
Int 21h
Mov ES,BX ; store PSP address in ES
Mov ES,ES:[002ch]; store PSP environment segment
; address in ES
Mov Env_Seg,ES ; save environment address
Xor DI,DI ; clear DI
Xor AL,AL ; clear AL
Mov CX,8000h ; assume environment segment
; is 32kb max
DoubleNullLoop:
Repne Scasb ; search using ES:DI
; until find a null
; (can't use scasw because the
; double null may fall on odd
; address)
Scasb ; find the second null
Jne DoubleNullLoop
Add DI,2 ; skip over markers
; db 0, 1
Mov Env_Len,DI ; save end of environment
; address
Mov AX,SS
Mov ES,AX ; set ES = to DGROUP for scasb
Assume ES:@data
Mov BX,[BP+8] ; get address of Path$
Mov AX,ES:[BX]
Cmp AX,64 ; if LEN(PATH$) <> 64
Jne Error12 ; then Error
Mov SI,ES:[BX+2] ; it has to be 64 so FileLength%
; value is calculated correctly below
Mov DI,SI ; copy SI:offset in DI for use by
; Movsb and Scasb below.
Push DI
Mov CX,64 ; copy Name into FName$
Mov DS,Env_Seg
Mov SI,Env_Len
Rep Movsb ; copy DS:SI to ES:DI
Mov CX,64 ; length of FName$
Xor AL,AL ; clear AL, the search value
Pop DI ; search for null at end of name
Repnz Scasb ; uses ES:DI to search
; scan until reach end of FName$
Mov AX,63 ; determine length of FName$
Sub AX,CX ; before the null
Jmp Short Finis12
Error12:
Mov AX,-1 ; return FileLength% = -1
; if error
Finis12:
Mov BX,[BP+6]
Mov ES:[BX],AX
Pop DS ; restore registers used
Pop DI
Pop SI
Pop BP
Ret 4 ; remove 2 * 2 parameters
GETCURRENTNAME ENDP
;============================================================================
; DECLARE SUB TRUENAME (OrigFile$+CHR$(0), TrueFName$, FileLength%)
; Purpose:
; Allows user to test for SUBST, ASSIGN, and JOIN using an
; undocumented call for DOS Version 3.xx and above
; The returned name will contain technically correct Drive: and Path
; information. However, the OrigFile$ is not checked so ? and * may be
; used, the OrigFile$ may even be non-existant.
;
; Shortcuts:
; OrigFile$ = "." to obtain current drive & subdirectory name
; OrigFile$ = ".." to obtain immediate parent drive & subdirectory name
;
; Usage:
; TrueFName$ = STR$(67,0)
; CALL TRUENAME(OrigFile$ + CHR$(0), TrueFName$, FileLength%)
; IF FileLength% = -1 THEN
; Error
; ELSE
; TrueFName$=LEFT$(TrueFName$, FileLength%)
; END IF
;============================================================================
EVEN
TRUENAME PROC FAR
Push BP
Mov BP,SP ; make stack addressable
Push DI ; save variables we use
Push SI
Mov AH,30h ; check if DOS version > 2.xx
Int 21h
Cmp AL,3 ; AL contains the major version
JB Error15 ; If less than 3.00, Error15
Mov BX,[BP+8] ; get TrueFName$
Mov CX,[BX] ; get length of string
JCXZ Error14 ; if zero, Error
Cmp CX,67 ; if not equal to 67 bytes, Error
JNE Error14
Mov DI,[BX+2] ; get address of TrueFName$ string
Mov BX,[BP+10] ; get length of OrigFile$
Mov CX,[BX] ; if length is zero, then Error
JCXZ Error14
Mov SI,[BX+2] ; get address of OrigFile$
Mov AX,DS ; faster than PUSH & POP on 8088
Mov ES,AX ; make ES==DS
Push DI ; save address of DI
; input string DS:SI, output ES:DI
Mov AH,60h ; call undocumented Expand Path Name
Int 21h ; Dettmann, DOS Programmer's Reference
; 2d Edition (Que 1989), page 660
; Very good book
Pop DI ; reset DI
JC Error14 ; bad character in OrigFile$
Mov CX,67 ; length of TrueFName$
Xor AL,AL ; clear AL, the search value
Cld ; clear the direction flag
Repnz Scasb ; uses ES:DI to search
; scan until reach end of TrueFName$
Mov AX,66 ; determine length of TrueFName$
Sub AX,CX ; before the null
Jmp Short Quit14 ; end routine
Error14:
Mov AX,-1 ; return a -1 for FileLength%
Quit14:
Mov BX,[BP+6]
Mov [BX],AX ; store AX in FileLength%
Pop SI ; restore saved registers
Pop DI
Pop BP
Ret 6 ; clear variables off stack
Error15: ; report DOS version is <3.xx
Xor AX,AX ; so no danger of SUBST, JOIN
Jmp Short Quit14 ; or ASSIGN
TRUENAME ENDP
;=========================================================================
; DECLARE SUB GETFULLPATH (PATH$, PATHLEN%)
; Returns current subdirectory path, with Drive:\, e.g. "A:\"
; if LEN(Path$) <> 67 then returns a pathlen% of -1
;
; PATH$ can not be a TYPEd string or a variable in a string array
; because there is a chance that string will be outside DGROUP.
; This routine assumes that Path$ is a near string.
;=========================================================================
EVEN
GETFULLPATH PROC FAR
Push BP ;set up base pointer
Mov BP,SP ;allow us to address the stack
Push SI ;save index registers
Push DI ; ditto
Mov BX,[BP+8] ;get address of Path$
Mov AX,[BX]
Cmp AX,67 ;if LEN(PATH$) <> 67
JNE Error2 ;then Error
Mov AX,SS
Mov ES,AX ;set ES == to DGROUP for scasb
assume ES:@data
Mov AH,19h ;get current drive
Int 21h
Add AL,'A' ;Add A to value
Xor AH,AH ;clear AH to 0
Mov BX,[BX+2] ;get actual string address
Mov Byte Ptr [BX],AL ;store AL in Drive$
Mov Byte Ptr [BX+1],':' ;add colon
Mov Byte Ptr [BX+2],'\' ;add backlash
ADD BX,3 ;increase address by 3 to skip "A:\"
Mov SI,BX ;it has to be 67 so Pathlen% value is
Mov DI,SI ;calculated correctly below
Xor DL,DL ;clear DL to get
Mov AH,47h ;get current directory
Int 21h
JC Error ;if carry set, directory invalid
Mov CX,64 ;find ending null in Path$
Xor AL,AL ;clear AL, the value to search for
Cld ;clear direction flag
Repnz Scasb ;uses ES:DI to search Path$
Mov AX,63 ;determine length of Path$
Sub AX,CX
Add AX,3 ;add length of drive "A:\"
Jmp Short finis2
Error2:
Mov AX,-1 ;return Pathlen% = -1 if error
finis2:
Mov BX,[BP+6]
Mov [BX],AX
Pop DI ;restore registers used
Pop SI
Pop BP
Ret 4
GETFULLPATH ENDP
END